/*
 * File:    RenderHookFactory.java
 * Created: 14-Oct-2007
 * Version: $Id$
 *
 * COPYRIGHT (C) 2007, Bitgate Software, LLC.  All Rights Reserved.
 *
 * software@bitgatesoftware.com
 */

package com.bitgate.util.service.protocol.http.render;

import static com.bitgate.util.debug.Debug.debug;
import static com.bitgate.util.debug.Debug.isDebugEnabled;
import static com.bitgate.util.debug.Debug.warning;

import java.util.HashMap;

import com.bitgate.util.config.Config;

/**
 * This factory class provides a uniform method to access the rendering system for the HTTP protocol layer.  This is still
 * only an example class; it is not meant for full production use.
 * 
 * @author kenji
 * @since 0.6.0
 */
public class RenderHookFactory
{
	private static final RenderHookFactory instance = new RenderHookFactory();
	private HashMap<String, Class<? extends RenderHookInterface>> knownServices;
	
	/**
	 * Creates a new render hook factory object.
	 */
	@SuppressWarnings("unchecked")
	private RenderHookFactory()
	{
		String templatesFilename = System.getProperty("templates.config");
		
		knownServices = new HashMap<String, Class<? extends RenderHookInterface>>();
		
		if (templatesFilename == null) {
			templatesFilename = "conf/defaults/templates.xml";
		}
		
		// Load in the system services file, and begin parsing through it to start the services necessary to run
		// the server.
		Config.getDefault().register(templatesFilename, "templates");
		
		int templates = Integer.parseInt(Config.getDefault().parseConfig("templates", "count(/templates/object)"));
		
		for(int i = 1; i < (templates + 1); i++) {
			String baseName = "/templates/object[" + i + "]";
			String objectName = Config.getDefault().parseConfig("templates", baseName + "/@name");
			String className = Config.getDefault().parseConfig("templates", baseName + "/property[@type='classname']/@value");
			String extension = Config.getDefault().parseConfig("templates", baseName + "/property[@type='extension']/@value");
			Class<? extends RenderHookInterface> templateClass = null;
			
			try {
				templateClass = (Class<? extends RenderHookInterface>) Class.forName(className);
			} catch(Exception e) {
				warning("Unable to load template class '" + className + ": " + e.getClass().getName());
				continue;
			}
			
			knownServices.put(extension, templateClass);
			
			if (isDebugEnabled()) {
				debug("Render hook registry: Name='" + objectName + "' className='" + className + "' extension='" + extension + "'");
			}
		}
	}
	
	/**
	 * Returns the static instance of this Singleton class.
	 * 
	 * @return <code>RenderHookFactory</code> object.
	 */
	public static RenderHookFactory getDefault()
	{
		return instance;
	}
	
	/**
	 * Determines whether or not a filename (or file extension) is renderable.
	 * 
	 * @param filename The <code>String</code> containing the filename (fully qualified filename) or the extension.
	 * @return <code>true</code> if the file is renderable, <code>false</code> otherwise.
	 */
	public boolean isRenderable(String filename)
	{
		String extension = filename;
		int periodPosition = -1;
		
		if ((periodPosition = filename.lastIndexOf(".")) != -1) {
			extension = filename.substring(periodPosition + 1);
		}
		
		return (knownServices.get(extension) != null);
	}
	
	/**
	 * Returns the appropriate <code>RenderHookInterface</code> used to render files of the type specified.
	 * 
	 * @param extension The <code>String</code> containing the name of the extension to use for rendering.
	 * @return <code>RenderHookInterface</code> if found, <code>null</code> otherwise.
	 */
	public RenderHookInterface getInterface(String extension)
	{
		RenderHookInterface rhInterface = null;
		
		try {
			rhInterface = knownServices.get(extension).newInstance();
		} catch(NullPointerException e) {
			warning("Unable to locate a render hook interface for extension '" + extension + "'");
			return null;
		} catch(IllegalAccessException e) {
			warning("Unable to access new render hook interface for extension '" + extension + "': " + e.getMessage());
			return null;
		} catch(InstantiationException e) {
			warning("Unable to instantiate a new render hook interface for extension '" + extension + "': " + e.getMessage());
			return null;
		}
		
		return rhInterface;
	}
}